package com.googlecode.utterlyidle.pdf;

import com.googlecode.utterlyidle.HttpHandler;
import com.googlecode.utterlyidle.HttpHeaders;
import com.googlecode.utterlyidle.Request;
import com.googlecode.utterlyidle.Response;
import com.googlecode.utterlyidle.ResponseBuilder;
import com.googlecode.utterlyidle.StreamingOutput;

import java.io.IOException;
import java.io.OutputStream;

import static com.googlecode.utterlyidle.HttpHeaders.ACCEPT;
import static com.googlecode.utterlyidle.MediaType.TEXT_HTML;
import static com.googlecode.utterlyidle.RequestBuilder.modify;

import com.lowagie.text.DocumentException;
import org.xhtmlrenderer.pdf.ITextRenderer;

import static com.googlecode.totallylazy.Predicates.is;

public class PdfHandler implements HttpHandler {
    public static final String APPLICATION_PDF = "application/pdf";

    private final HttpHandler decorated;
    private LinkRewriter linkRewriter;

    public PdfHandler(HttpHandler decorated, LinkRewriter linkRewriter) {
        this.decorated = decorated;
        this.linkRewriter = linkRewriter;
    }

    @Override
    public Response handle(Request request) throws Exception {
        if(!request.headers().valueOption(ACCEPT).exists(is(APPLICATION_PDF)))
            return decorated.handle(request);

        Request htmlRequest = modify(request).replaceHeader(ACCEPT, TEXT_HTML).build();
        final Response htmlResponse = linkRewriter.apply(request, decorated.handle(htmlRequest));
        return ResponseBuilder.modify(htmlResponse)
                .entity(pdfStreamer(htmlResponse))
                .replaceHeaders(HttpHeaders.CONTENT_TYPE, APPLICATION_PDF)
                .build();
    }

    private StreamingOutput pdfStreamer(final Response htmlResponse) {
        return new StreamingOutput() {
            @Override
            public void write(OutputStream outputStream) throws IOException {
                ITextRenderer renderer = new ITextRenderer();
                renderer.setDocumentFromString(htmlResponse.entity().toString());
                renderer.layout();
                try {
                    renderer.createPDF(outputStream);
                } catch (DocumentException e) {
                    throw new IOException(e);
                }
            }
        };
    }
}

